package com.kaka.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class MyJDBCUtil {
    private static String driver = null;
    private static String url = null;
    private static String user = null;
    private static String password = null;

    public MyJDBCUtil() {
    }

    static {
        ClassLoader classLoader = MyJDBCUtil.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();

        try {
            properties.load(is);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        driver = properties.getProperty("driver");
        url = properties.getProperty("url");
        user = properties.getProperty("user");
        password = properties.getProperty("password");
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getCon() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return connection;
    }

    public static void close(ResultSet rs, Statement st, Connection con) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static int dmlSQL(String sql, Object... objects) {
        Connection con = MyJDBCUtil.getCon();
        PreparedStatement statement = null;
        int count = 0;
        try {
            statement = con.prepareStatement(sql);
            for (int i = 0; i < objects.length; i++) {
                statement.setObject(i + 1, objects[i]);
            }
            count = statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            MyJDBCUtil.close(null, statement, con);
        }
        return count;
    }

    /**
     * dql语句查询方法
     * @param c 传入orm映射对象的class对象 并且
     * @param sql 执行的sql语句 参数使用?占位符替换
     * @param obj 对应占位符传入的数据 必须与?占位符匹配
     * @param <E> 当前sql处理后返回的集合中的数据类型
     * @return 所有对应类型数据的集合
     */
    public static<E> List<E> dqlSQL(Class<E> c,String sql,Object ...obj){
        List<E> list=new ArrayList<>();
        Connection con = getCon();
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            ps = con.prepareStatement(sql);
            for (int i = 0; i < obj.length; i++) {
                ps.setObject(i+1,obj[i]);
            }
            rs = ps.executeQuery();
            while(rs.next()){
                //获取传入类型的无参构造方法
                Constructor<E> declaredConstructor = c.getDeclaredConstructor();
                //调用创建对象
                declaredConstructor.setAccessible(true);
                E e = declaredConstructor.newInstance();
                //基于ORM对象关系映射 默认情况下我们要求 列名与属性名相同
                //获取所有的属性
                Field[] declaredFields = c.getDeclaredFields();
                //遍历属性
                for (Field declaredField : declaredFields) {
                    String fieldName=declaredField.getName();
                    //获取当前对应列的值
                    Object fieldValue= rs.getObject(fieldName);

                    declaredField.setAccessible(true);
                    //为对应对象 对应属性赋值
                    declaredField.set(e,fieldValue);
                    //System.out.print(fieldValue+" ");
                }
                //System.out.println();
                list.add(e);
            }
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }finally {
            close(rs,ps,con);
        }
        return list;
    }
}
